"""
Case Type   : 系统内部使用工具
Case Name   : 1+2备在被减容的备库执行gs_uninstall --delete-data -L
Create At   : 2022/04/11
Owner       : opentestcase018
Description :
    1.执行gs_dropnode进行减容：
    ./gs_dropnode -U {usrname} -G {grp_name} -h {hostname}
    2.在减容备机上执行gs_uninstall --delete-data卸载数据库
    3.恢复环境
Expect      :
    1.减容成功
    2.备机数据库卸载成功，集群状态1+1
    3.恢复成功
History     :
    2022-6-06 opentestcase039 优化用例，根据自动化连跑要求，改为在源库上操作
    2022-7-01 opentestcase039 优化用例，增加检查gs_sshexkey工具步骤,根据代码修改优化扩容步骤为不需要密码交互
    2022-8-03 opentestcase039 优化用例，增加检查stand_name后断言
"""
import os
import unittest
from testcase.utils.Common import Common
from testcase.utils.Common import CommonSH
from testcase.utils.Constant import Constant
from testcase.utils.Logger import Logger
from yat.test import Node
from yat.test import macro
COMMONSH = CommonSH("PrimaryDbUser")
Constant = Constant()


@unittest.skipIf(3 != COMMONSH.get_node_num(), '非1+2环境不执行')
class Tools(unittest.TestCase):
    def setUp(self):
        self.log = Logger()
        self.common = Common()
        self.log.info(f'----{os.path.basename(__file__)} start----')
        self.primary_root_node = Node('PrimaryRoot')
        self.primary_node = Node('PrimaryDbUser')
        self.standby1_root_node = Node('Standby1Root')
        self.standby1_node = Node('Standby1DbUser')
        self.standby2_node = Node('Standby2DbUser')
        self.standby2_root_node = Node('Standby2Root')
        self.com_root = CommonSH("PrimaryRoot")
        self.com_user = CommonSH("PrimaryDbUser")
        self.s_com1 = CommonSH("Standby1DbUser")
        self.s_com2 = CommonSH("Standby2DbUser")
        self.u_name = self.primary_node.ssh_user
        self.pkg_path = os.path.dirname(macro.DB_SCRIPT_PATH)
        num = COMMONSH.get_node_num()
        self.assertGreaterEqual(num, 3, "执行失败:节点数量异常，减容不执行")

        self.log.info("查询synchronous_standby_names默认值")
        result = COMMONSH.execut_db_sql("show synchronous_standby_names")
        self.assertIn('synchronous_standby_names', result, '获取失败')
        self.log.info(f"primary synchronous_standby_names is {result}")
        self.synchronous_standby_names_p = result.strip().splitlines()[-2]
        result = self.s_com1.execut_db_sql("show synchronous_standby_names")
        self.assertIn('synchronous_standby_names', result, '获取失败')
        self.log.info(f"s1 synchronous_standby_names is {result}")
        self.synchronous_standby_names_s1 = result.strip().splitlines()[-2]
        result = self.s_com2.execut_db_sql("show synchronous_standby_names")
        self.assertIn('synchronous_standby_names', result, '获取失败')
        self.log.info(f"s2 synchronous_standby_names is {result}")
        self.synchronous_standby_names_s2 = result.strip().splitlines()[-2]

        self.host_tuple = (self.primary_node.ssh_host,
                           self.standby1_node.ssh_host,
                           self.standby2_node.ssh_host)
        self.params = {'-f': 'test_hosts'}

    def test_gs_dropnode(self):
        text = '----step1:执行gs_dropnode进行备机减容 expect:成功'
        self.log.info(text)
        drop_cmd = f'gs_dropnode -U {self.u_name} -G {self.u_name} ' \
                   f'-h {self.standby1_root_node.ssh_host}'
        self.log.info(drop_cmd)
        global shell_path
        shell_path = os.path.join('/', 'home', f'{self.u_name}', 'dropnode.sh')
        shell_cmd = f'touch {shell_path};echo -e {drop_cmd} > {shell_path};' \
                    f'chmod 755 {shell_path};cat {shell_path}'
        self.log.info(shell_cmd)
        shell_res = self.primary_root_node.sh(shell_cmd).result()
        self.log.info(shell_res)
        drop_cmd = f'''source {macro.DB_ENV_PATH}
                       expect <<EOF
                       set timeout 200
                       spawn {shell_path}
                       expect "(yes/no)?"
                       send "yes\\n"
                       expect eof\n''' + '''EOF'''
        self.log.info(drop_cmd)
        drop_res = self.primary_node.sh(drop_cmd).result()
        self.log.info(drop_res)
        self.assertIn('Success to drop the target nodes', drop_res,
                      text + '减容失败')

        self.log.info('检查数据库是否减容')
        check_cmd = f'source {macro.DB_ENV_PATH};' \
                    f'gs_om -t status --detail;'
        self.log.info(check_cmd)
        check_res = self.primary_node.sh(check_cmd).result()
        self.log.info(check_res)
        self.assertNotIn(self.standby1_node.ssh_host, check_res, '数据库状态检查失败')

        text = "----step2:在减容备机上执行卸载数据库 expect:成功----"
        self.log.info(text)
        text_1 = '----gs_uninstall卸载数据库----'
        self.log.info(text_1)
        execute_cmd = f'source {macro.DB_ENV_PATH};' \
                      f'gs_uninstall --delete-data -L;'
        self.log.info(execute_cmd)
        uninstall_msg = self.standby1_node.sh(execute_cmd).result()
        self.log.info(uninstall_msg)
        self.assertIn(Constant.uninstall_success_msg, uninstall_msg, '卸载失败')

        self.log.info('检查数据库状态')
        check_cmd = f'source {macro.DB_ENV_PATH};' \
                    f'gs_om -t status --detail;'
        self.log.info(check_cmd)
        check_res = self.primary_node.sh(check_cmd).result()
        self.log.info(check_res)
        for check_msg in [self.primary_node.ssh_host,
                          self.standby2_node.ssh_host]:
            self.assertIn(check_msg, check_res, '数据库状态检查失败')

    def tearDown(self):
        text = "----step3:恢复环境 expect:成功----"
        self.log.info(text)
        self.log.info('-----创建root互信-----')
        result = self.common.get_sh_result(self.primary_root_node,
                                           f"ls {macro.DB_SCRIPT_PATH}")
        if "gs_sshexkey" not in result:
            cmd = f"cd {macro.DB_SCRIPT_PATH}/../; " \
                  f"tar -zxvf openGauss-Package-bak*.tar.gz > /dev/null"
            result = self.primary_root_node.sh(cmd).result()
            self.log.info(result)
            result = self.common.get_sh_result(self.primary_root_node,
                                               f"ls {macro.DB_SCRIPT_PATH}")
            self.log.info(result)
            if "gs_sshexkey" not in result:
                raise Exception("cat not find gs_sshexkey, Please check!")
        self.com_root.exec_gs_sshexkey(macro.DB_SCRIPT_PATH,
                                       *self.host_tuple,
                                       **self.params)
        om_name = self.common.get_sh_result(self.standby2_root_node,
                                            f"ls {self.pkg_path} | "
                                            f"grep 'om.tar.gz'")
        result = self.common.get_sh_result(self.primary_root_node,
                                           f"ls {self.pkg_path}")
        if om_name not in result:
            cmd = f"cd {self.pkg_path};" \
                  f"scp {om_name} root@" \
                  f"{self.primary_node.ssh_host}:{self.pkg_path}"
            result = self.standby2_root_node.sh(cmd).result()
            self.log.info(result)
            result = self.common.get_sh_result(self.primary_root_node,
                                               f"ls {self.pkg_path}")
            self.log.info(result)
            if om_name not in result:
                raise Exception("cat not find package_om, Please check!")
        expansion_cmd = f'cd {macro.DB_SCRIPT_PATH};' \
                        f'source {macro.DB_ENV_PATH};' \
                        f'./gs_expansion -U {self.u_name} -G {self.u_name} ' \
                        f'-X {macro.DB_XML_PATH} -h ' \
                        f'{self.standby1_node.ssh_host}'
        self.log.info(expansion_cmd)
        execute_cmd = f'''cd {macro.DB_SCRIPT_PATH};
                           source {macro.DB_ENV_PATH};
                           expect <<EOF
                           set timeout 300
                           spawn {expansion_cmd}
                           expect "*assword*:"
                           send "{macro.COMMON_PASSWD}\\n"
                           expect "*assword*:"
                           send "{macro.COMMON_PASSWD}\\n"
                           expect "*lease repeat for database*:"
                           send "{macro.COMMON_PASSWD}\\n"
                           expect eof\n''' + '''EOF'''
        self.log.info(execute_cmd)
        expan_result = self.primary_root_node.sh(expansion_cmd).result()
        self.log.info(expan_result)
        check_msg = f'Expansion results:\n' \
                    f'{self.standby1_node.ssh_host}:\tSuccess\n' \
                    f'Expansion Finish.'
        self.log.info(check_msg)
        self.log.info('-----删除创建文件-----')
        del_cmd = f"rm -rf {shell_path}"
        self.log.info(del_cmd)
        del_res = self.primary_root_node.sh(del_cmd).result()
        self.log.info(del_res)
        self.log.info('检查是否扩容成功')
        check_cmd = f'source {macro.DB_ENV_PATH};' \
                    f'gs_om -t status --detail;'
        self.log.info(check_cmd)
        check_res = self.primary_node.sh(check_cmd).result()
        self.log.info(check_res)
        self.log.info("恢复各节点synchronous_standby_names")
        COMMONSH.execute_gsguc("reload",
                               Constant.GSGUC_SUCCESS_MSG,
                               f"synchronous_standby_names="
                               f"'{self.synchronous_standby_names_p}'",
                               single=True)
        self.s_com1.execute_gsguc("reload",
                                  Constant.GSGUC_SUCCESS_MSG,
                                  f"synchronous_standby_names="
                                  f"'{self.synchronous_standby_names_s1}'",
                                  single=True)
        self.s_com2.execute_gsguc("reload",
                                  Constant.GSGUC_SUCCESS_MSG,
                                  f"synchronous_standby_names="
                                  f"'{self.synchronous_standby_names_s2}'",
                                  single=True)
        self.assertIn(check_msg, expan_result, text + '执行失败')
        self.assertIn(self.standby1_node.ssh_host, check_res, '扩容后检查失败')
        self.assertEqual('', del_res, '文件删除失败')
        self.log.info(f'----{os.path.basename(__file__)} finish----')
